package com.xcity.game.formation;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import com.alibaba.fastjson.JSON;
import com.xcity.db.entity.Employee;
import com.xcity.db.entity.Player;
import com.xcity.game.combat.CombatException;
import com.xcity.game.employee.EmployeeListener;

public class FormationManager implements EmployeeListener {

	protected Player owner;
	protected List<Formation> formations; // 所有阵型
	private List<Employee> sortedEmployees; // 所有员工（按战斗力排序）
	private boolean reorder;
	
	public FormationManager(List<long[]> employeeIds) {
		this(null, employeeIds);
	}
	
	public FormationManager(Player owner, List<long[]> employeeIds) {
		this.owner = owner;
		if (employeeIds != null) {
			this.formations = new ArrayList<Formation>(employeeIds.size());
			for (int i = 0; i < employeeIds.size(); i++) {
				this.formations.add(new Formation(owner, employeeIds.get(i), (byte) i));
			}
		}
	}
	
	public void setOwner(Player player) {
		this.owner = player;
		if (formations != null) {
			for (int i = formations.size() - 1; i >= 0; i--) {
				formations.get(i).setOwner(player);
			}
		}
	}
	
	public Formation get(byte type) {
		if (Formation.isValid(type)) {
			if (formations == null) {
				formations = new ArrayList<Formation>(3);
			}
			while (formations.size() <= type) {
				byte _type = (byte) formations.size();
				Formation f = new Formation(owner, _type);
				fastSet(f);
				formations.add(f);
			}
			Formation f = formations.get(type);
			f.validate();
			return f;
		}
		return null;
	}
	
	public synchronized long[] fastSet(Formation formation) {
		// 先批量下阵
		for (int i = 0, len = Formation.FORMATION_CAPCITY; i < len; i++) {
			try {
				formation.replace(i, null);
			} catch (CombatException e) {
			}
		}
		// 再按序上阵
		List<Employee> list = initEmployees();
		int offset = 0;
		for (int i = 0; i < list.size(); i++) {
			Employee employee = list.get(i);
			try {
				formation.replace(offset, employee);
				++offset;
			} catch (CombatException e) {
			}
		}
//		formation.validate();
		return formation.getIds();
	}
	
	static Comparator<Employee> COMP = new Comparator<Employee>() {
		@Override
		public int compare(Employee e1, Employee e2) {
			int c1 = e1.getCombatPower();
			int c2 = e2.getCombatPower();
			if (c1 < c2) {
				return 1;
			}
			if (c1 > c2) {
				return -1;
			}
			return e1.getId() > e2.getId() ? 1 : -1;
		}
	};
	
//	Comparator<Employee> COMP_PEAK_ROAD = new Comparator<Employee>() {
//		@Override
//		public int compare(Employee e1, Employee e2) {
//			if (owner.getPeakRoadInstance().isDied(e1)) {
//				return 1;
//			}
//			if (owner.getPeakRoadInstance().isDied(e2)) {
//				return -1;
//			}
//			return COMP.compare(e1, e2);
//		}
//	};
	
	@Override
	public void fireEmployeeAdded(Employee employee) {
		synchronized (this) {
			if (sortedEmployees == null) {
				initEmployees();
				return;
			}
			sortedEmployees.add(employee);
			Collections.sort(sortedEmployees, COMP);
		}
		
	}
	
	@Override
	public void fireEmployeeRemoved(Employee employee) {
		remove(employee);
		synchronized (this) {
			if (sortedEmployees == null) {
				initEmployees();
				return;
			}
			sortedEmployees.remove(employee); // 依然有序
		}
	}
	
	public void remove(Employee employee) {
		if (formations != null) {
			for (int i = formations.size() - 1; i >= 0; i--) {
				formations.get(i).remove(employee);
			}
		}
	}
	
	private synchronized List<Employee> initEmployees() {
		if (sortedEmployees == null) {
			Collection<Employee> all = owner.getEmployees().getEmployees();
			sortedEmployees = new ArrayList<>(all.size() + 10);
			for (Employee e : all) {
				sortedEmployees.add(e);
			}
			Collections.sort(sortedEmployees, COMP);
		}
		return sortedEmployees;
	}
	
	protected void fireCombatPowerChanged() {
		if (reorder) {
			return;
		}
		reorder = true;
		synchronized (this) {
			if (sortedEmployees == null) {
				initEmployees();
				return;
			}
			Collections.sort(sortedEmployees, COMP);
		}
		reorder = false;
	}

	@Override
	public String toString() {
		if (formations != null) {
			long[][] dup = new long[formations.size()][];
			for (int i = 0; i < formations.size(); i++) {
				dup[i] = formations.get(i).getIds();
			}
			return JSON.toJSONString(dup);
		}
		return null;
	}
	
}
